/*      Copyright 2010 Jesus McCloud <bernd.pruenster@gmail.com>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 3 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 * 
 *      This is the GUI, it quite complete but the parser requires some work
 *      to fully support everything Gtk.Builder supports
 */

//compile with --pkg gtksourceview-2.0 --pkg libxml-2.0 --pkg gtk+-2.0  --pkg gmodule-2.0 --pkg gee-1.0


using Gtk;

namespace jmc{
public class GladeV : GLib.Object{
  const string GLADE ="GladeV.glade";

  private string file_name;
/*Widget Declaration*/
  private Gtk.ListStore widget_table;  
  private Gtk.TreeViewColumn column_widget;
  private Gtk.TreeViewColumn column_toggle;  
  private Gtk.ComboBox cb_main_window;
  private Gtk.VBox vbox4;
  private Gtk.ComboBox cb_select_template;
  private Gtk.HButtonBox dialog_action_area1;
  private Gtk.VBox dialog_vbox1;
  private Gtk.Label lb_status;
  private Gtk.Button bt_generate;
  private Gtk.Button bt_all;
  private Gtk.Button bt_with_handlers;
  private Gtk.Button bt_none;
  private Gtk.TreeViewColumn widget_column;
  private Gtk.TreeViewColumn toggle_column;
  private Gtk.TreeView treeview1;
  private Gtk.Frame table_frame;
  private Gtk.HBox hbox4;
  private Gtk.Entry entry_class;
  private Gtk.Entry entry_namespace;
  private Gtk.SourceView tv_source;
  private Gtk.ImageMenuItem mi_about;
  private Gtk.ImageMenuItem mi_quit;
  private Gtk.ImageMenuItem mi_save;
  private Gtk.ImageMenuItem mi_open;
  private jmc.Parser gladeParser;
  private Gtk.Frame frame2;
  public Gtk.Window main_window {get; set;}
  
  
  Gtk.SourceBuffer syntax_highlight;
  Gtk.SourceLanguageManager lang_man;
  
/*Default Constructor*/
  public GladeV(){
    file_name="Glade-xml";
    gladeParser= new jmc.Parser();
    create_ui();
    string name;
    try{
    var d = Dir.open("templates");
    while ((name = d.read_name()) != null) {
      cb_select_template.append_text(name);
      cb_select_template.set_active(0);
    }
  }catch(FileError e){}
    
    gladeParser.init_template("templates/"+cb_select_template.get_active_text());
    syntax_highlight = new Gtk.SourceBuffer(null);
    lang_man = Gtk.SourceLanguageManager.get_default();
    tv_source.buffer.text="Open a Glade XML file to start...";
  }



  private void create_ui(){
    try
    {
      Gtk.Builder builder  =  new Gtk.Builder ();
      builder.add_from_file (GLADE);
         
/*Widget Creation*/
      dialog_action_area1 = builder.get_object("dialog-action_area1") as Gtk.HButtonBox;

      dialog_vbox1 = builder.get_object("dialog_vbox1") as Gtk.VBox;

      lb_status = builder.get_object("lb_status") as Gtk.Label;

      bt_generate = builder.get_object("bt_generate") as Gtk.Button;
      bt_generate.clicked+=(on_bt_generate_clicked);

      bt_all = builder.get_object("bt_all") as Gtk.Button;
      bt_all.clicked+=(on_bt_all_clicked);

      bt_with_handlers = builder.get_object("bt_with_handlers") as Gtk.Button;
      bt_with_handlers.clicked+=(on_bt_with_handlers_clicked);

      bt_none = builder.get_object("bt_none") as Gtk.Button;
      bt_none.clicked+=(on_bt_none_clicked);

      widget_column = builder.get_object("widget_column") as Gtk.TreeViewColumn;

      toggle_column = builder.get_object("toggle_column") as Gtk.TreeViewColumn;

      treeview1 = builder.get_object("treeview1") as Gtk.TreeView;

      table_frame = builder.get_object("table_frame") as Gtk.Frame;

      hbox4 = builder.get_object("hbox4") as Gtk.HBox;
      
      cb_main_window= new Gtk.ComboBox.text();
      cb_main_window.append_text("");
      cb_main_window.set_active(0);
      hbox4.add(cb_main_window);

      
      entry_class = builder.get_object("entry_class") as Gtk.Entry;

      entry_namespace = builder.get_object("entry_namespace") as Gtk.Entry;

      tv_source = builder.get_object("tv_source") as Gtk.SourceView;

      mi_about = builder.get_object("mi_about") as Gtk.ImageMenuItem;
      mi_about.activate+=(on_mi_about_activate);

      mi_quit = builder.get_object("mi_quit") as Gtk.ImageMenuItem;
      mi_quit.activate+=(on_mi_quit_activate);

      mi_save = builder.get_object("mi_save") as Gtk.ImageMenuItem;
      mi_save.activate+=(on_mi_save_activate);

      mi_open = builder.get_object("mi_open") as Gtk.ImageMenuItem;
      mi_open.activate+=(on_mi_open_activate);

      main_window = builder.get_object("main_window") as Gtk.Window;

      vbox4 = builder.get_object("vbox4") as Gtk.VBox;

      frame2 = builder.get_object("frame2") as Gtk.Frame;
      cb_select_template = new Gtk.ComboBox.text();
      frame2.add(cb_select_template);
      
      widget_table = builder.get_object("widget_table") as ListStore;
      
      column_toggle = builder.get_object("toggle_column") as Gtk.TreeViewColumn;
      column_widget = builder.get_object("widget_column") as Gtk.TreeViewColumn;
      
      var renderer_toggle = new CellRendererToggle ();
      column_toggle.pack_start(renderer_toggle, false);
      column_toggle.add_attribute (renderer_toggle, "active", 0);
      var renderer_text = new CellRendererText ();
      column_widget.pack_start (renderer_text, true);
      column_widget.add_attribute (renderer_text, "text", 1);
        
      renderer_toggle.toggled.connect(on_table_toggled);
      
/*Connect Destroy*/
      main_window.destroy.connect(Gtk.main_quit);

    }catch (GLib.Error e) {
        stderr.printf ("Could not load UI: %s\n", e.message);
    }
  }
  
  
  private void fill_table(){
    widget_table.clear();
    TreeIter iter;
    for(int i=0;i<gladeParser.widgets.size;i++){         
        widget_table.append (out iter);
        widget_table.set (iter, 0, true, 1, ((gladeParser.widgets.get(i)).split(";"))[1]);
    }
  }
  
  private void clear_cbox(){
     for(int i=gladeParser.widgets.size-1;i>=0;i--){
        cb_main_window.remove_text(1);
      }
  }
  
  
  private void setup_cbox(){
    int[] indices= gladeParser.init_widget_indices(widget_table);
    clear_cbox();
    string[] temp;
    for(int i=0;i<indices.length;i++){
      temp=(gladeParser.widgets.get(indices[i]).split(";"));
        cb_main_window.append_text(temp[1]);
    }
  }
  
  
/*Signal Handlers*/
  private void on_table_toggled(CellRendererToggle toggle, string path){
    var tree_path = new TreePath.from_string (path);
    TreeIter iter;
    widget_table.get_iter (out iter, tree_path);
    widget_table.set (iter, 0, !toggle.active);
    setup_cbox();
  }
  
  [CCode (instance_pos = -1)]
  private void on_bt_generate_clicked(Gtk.Button source){
    
    gladeParser.init_template("templates/"+cb_select_template.get_active_text());
    tv_source.buffer = new Gtk.SourceBuffer.with_language(lang_man.get_language("vala"));
    
    gladeParser.create_body_head(entry_namespace.text, entry_class.text, file_name);
    gladeParser.create_body_variables(cb_main_window.get_active_text(),widget_table);
    gladeParser.create_constructor();
    gladeParser.create_widgets(widget_table);
    if(cb_main_window.get_active_text()!="")
      gladeParser.create_connect_destroy(cb_main_window.get_active_text());
    else gladeParser.create_connect_destroy(null);
    gladeParser.create_handlers(widget_table);
    if(cb_main_window.get_active_text()!="")
      gladeParser.create_object_and_run(cb_main_window.get_active_text());
    else gladeParser.create_object_and_run(null);
    tv_source.buffer.text=gladeParser.generate_code();
    mi_save.set_sensitive(true);
    
    //valac --pkg gtksourceview-2.0 --pkg libxml-2.0 --pkg gtk+-2.0  --pkg gmodule-2.0 --pkg gee-1.0 "Parser.vala" (in directory: /home/jesus/Documents/vala/Parser)
    
  }

  [CCode (instance_pos = -1)]
  private void on_bt_none_clicked(Gtk.Button source){
    TreeIter iter;
    for(int i=0;i<gladeParser.widgets.size;i++){
      widget_table.get_iter (out iter, new TreePath.from_indices(i));
      widget_table.set (iter, 0, false);
    }
   
    clear_cbox();
  }

  [CCode (instance_pos = -1)]
  private void on_bt_all_clicked(Gtk.Button source){
    TreeIter iter;
    for(int i=0;i<gladeParser.widgets.size;i++){
      widget_table.get_iter (out iter, new TreePath.from_indices(i));
      widget_table.set (iter, 0, true);
    }
    gladeParser.init_widget_indices(widget_table);
    clear_cbox();
    
    for(int i=0;i<gladeParser.widgets.size;i++){
      cb_main_window.append_text(gladeParser.widgets[i].split(";")[1]);
    }    
  }

  [CCode (instance_pos = -1)]
  private void on_mi_save_activate(Gtk.ImageMenuItem source){
  var filechooser = new Gtk.FileChooserDialog("Save File",
      main_window,Gtk.FileChooserAction.SAVE, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
      Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT, null);
    
    if(filechooser.run()==Gtk.ResponseType.ACCEPT){
      try{
        FileUtils.set_contents(filechooser.get_filename(),tv_source.buffer.text);
        lb_status.label="File saved!";
      }catch(GLib.Error e)
      {
        lb_status.label="Error saving file!";
      }
    }
    filechooser.destroy();
  }

  [CCode (instance_pos = -1)]
  private void on_mi_quit_activate(Gtk.ImageMenuItem source){
  
  }

  [CCode (instance_pos = -1)]
  private void on_bt_with_handlers_clicked(Gtk.Button source){
  TreeIter iter;
  clear_cbox();
  string[] temp;
    for(int i=0;i<gladeParser.widgets.size;i++){
      widget_table.get_iter (out iter, new TreePath.from_indices(i));
      temp=(gladeParser.widgets.get(i).split(";"));
      if(temp.length==3){
        widget_table.set (iter, 0, false);
      }else{
        widget_table.set (iter, 0, true);
        cb_main_window.append_text(temp[1]);
      }
    }
  }

  [CCode (instance_pos = -1)]
  private void on_mi_about_activate(Gtk.ImageMenuItem source){
     try
    {
      Gtk.Builder builder  =  new Gtk.Builder ();
      builder.add_from_file (GLADE);

      var aboutdialog1 = builder.get_object("aboutdialog1") as Gtk.AboutDialog;
      
  aboutdialog1.run();
  aboutdialog1.destroy();
    }catch(Error e){}
  }

  [CCode (instance_pos = -1)]
  private void on_mi_open_activate(Gtk.ImageMenuItem source){  
    var filechooser = new Gtk.FileChooserDialog("Open File",
    main_window,Gtk.FileChooserAction.OPEN, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
    Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT, null);
    string filename;//=filechooser.get_filename();
    if(filechooser.run()==Gtk.ResponseType.ACCEPT){
      filename=filechooser.get_filename();
      gladeParser.open_file(filename);
      gladeParser.file_opened=true;  
      string[]filenames= filechooser.get_filename().split("/");
      file_name= filenames[filenames.length-1];
      
      filechooser.destroy();
      fill_table();
      setup_cbox();
       try{
        string tmp;
        FileUtils.get_contents(filename,out tmp,null);
        tv_source.buffer = new Gtk.SourceBuffer.with_language(lang_man.get_language("xml"));
        tv_source.buffer.text=tmp;
        lb_status.label=filename+" loaded.";
        bt_generate.sensitive=true;
      }catch(GLib.Error e){
        tv_source.buffer.text="ERROR";
        lb_status.label="Error loading File "+filename+"!";
      }
    }
  
  }


}

int main (string[] args)
{
    Gtk.init (ref args);
/*Create new Object of Class*/
    GladeV gladev =  new GladeV();
    gladev.main_window.show_all ();

    Gtk.main ();
    return 0;
}

}

